import pygame
from pygame import *
import time
import random

# 定义玩家飞机类
class HeroPlane(pygame.sprite.Sprite):
    #存放飞机子弹的组
    bullets = pygame.sprite.Group()

    def __init__(self, screen):
        # 精灵类初始化方法，必须调用
        pygame.sprite.Sprite.__init__(self)

        # 创建飞机图片
        self.player = pygame.image.load("./images/me1.png") #102*126
        self.rect = self.player.get_rect()# rect矩型
        self.rect.topleft = [480 / 2 - 100 / 2,500]

        self.speed = 4
        # 记录当前窗口的对象
        self.screen = screen
        # 用来装子弹的列表
        self.bullets = pygame.sprite.Group()

    # 控制飞机移动
    def key_control(self):
        key_pressed = pygame.key.get_pressed()

        if key_pressed[K_w] or key_pressed[K_UP]:
            self.rect.top -= self.speed
        if key_pressed[K_s] or key_pressed[K_DOWN]:
            self.rect.bottom += self.speed
        if key_pressed[K_a] or key_pressed[K_LEFT]:
            self.rect.left -= self.speed
        if key_pressed[K_d] or key_pressed[K_RIGHT]:
            self.rect.right += self.speed
        if key_pressed[K_SPACE]:
            # 按空格键发射子弹
            bullet = Bullet(self.screen, self.rect.left, self.rect.top)
            self.bullets.add(bullet)

            HeroPlane.bullets.add(bullet)

    def update(self):
        self.key_control()
        self.display()

    def display(self):
        # 将飞机图片粘贴到窗口中
        self.screen.blit(self.player, self.rect)
        # 更新子弹位置
        self.bullets.update()
        # 在屏幕上显示子弹
        self.bullets.draw(self.screen)
    @classmethod
    def clear_bullets(cls):
        # 清空子弹
        cls.bullets.empty()


# 定义子弹类
class Bullet(pygame.sprite.Sprite):
    def __init__(self, screen, x, y):
        # 精灵类初始化方法，必须调用
        pygame.sprite.Sprite.__init__(self)

        self.image = pygame.image.load("./images/bullet2.png") # 5*11
        # 坐标
        self.rect = self.image.get_rect()  # rect: 矩型
        self.rect.topleft = [x + 140/2 - 15/2, y - 62]

        self.screen = screen
        self.speed = 10

    def update(self):
        # 实时更新子弹坐标
        self.rect.top -= self.speed
        # 当子弹移除屏幕时销毁子弹
        if self.rect.top < -62:
            self.kill()

# 定义敌方飞机的类
class EnemyPlane(pygame.sprite.Sprite):
    # 存放敌方飞机子弹
    enemy_bullets = pygame.sprite.Group()
    def __init__(self, screen):
         # 精灵类初始化方法，必须调用
        pygame.sprite.Sprite.__init__(self)

        self.player = pygame.image.load("./images/enemy1.png") # 57*43
        self.rect = self.player.get_rect()  # rect: 矩型
        x = random.randrange(1, Manager.bg_size[0], 50)
        self.rect.topleft = [x, 0]
        self.speed = 2
        self.screen = screen
        self.direction = "right"

        self.bullets = pygame.sprite.Group()  # 用来装子弹的列表

    def display(self):
        # 将敌方飞机图片粘贴到窗口中
        self.screen.blit(self.player, self.rect)
        # 更新子弹位置
        self.bullets.update()
        # 在屏幕上显示子弹
        self.bullets.draw(self.screen)

    def auto_move(self):
        if self.direction == "right":
            self.rect.right += self.speed
        elif self.direction == "left":
            self.rect.right -= self.speed
        if self.rect.right > 480-15:
            self.direction = "left"
        elif self.rect.right < 0:
            self.direction = "right"
        self.rect.bottom += self.speed

    def auto_fire(self):
        random_num = random.randint(1,50)
        if random_num == 1:
            bullet = EnemyBullet(self.screen, self.rect.left, self.rect.top)
            self.bullets.add(bullet)
            EnemyPlane.enemy_bullets.add(bullet)

    def update(self):
        self.auto_move()
        self.auto_fire()
        self.display()

    @classmethod
    def clear_bullets(cls):
        cls.enemy_bullets.empty()

#定义敌方子弹类
class EnemyBullet(pygame.sprite.Sprite):
    def __init__(self, screen, x, y):
        # 精灵类初始化方法，必须调用
        pygame.sprite.Sprite.__init__(self)

        self.image = pygame.image.load("./images/bullet1.png")# 5*11
        # 坐标
        self.rect = self.image.get_rect()  # rect: 矩型
        self.rect.topleft = [x + 24/ 2 - 24 / 2, y + 24]
        self.screen = screen
        self.speed = 8

    def update(self):
        # 实时更新子弹坐标
        self.rect.top += self.speed
        # 当子弹移除屏幕时销毁子弹
        if self.rect.top > 724:
            self.kill()

# 定义爆炸类
class Bomb(object):
    def __init__(self,screen,type):
        self.screen = screen
        if type == "enemy":
            self.mImage = [pygame.image.load
                            ("./images/enemy1_down" + str(i) + ".png")for i in range(1,5)]

        else:
            self.mImage = [pygame.image.load
                            ("./images/me_destroy_" + str(i) + ".png")for i in range(1,5)]

        self.mIndex = 0

        self.mPos = [0,0]

        self.mVisible = False

    def action(self,rect):
        # 触发爆炸方法draw
        # 爆炸的坐标
        self.mPos[0] = rect.left
        self.mPos[1] = rect.top
        # 打开爆炸的开关
        self.mVisible = True

    def draw(self):
        if not self.mVisible:
            return
        self.screen.blit(self.mImage[self.mIndex], (self.mPos[0], self.mPos[1]))
        self.mIndex += 1
        if self.mIndex >=len(self.mImage):
            # 如果下标到达最后，表示爆炸结束
            self.mIndex = 0
            self.mVisible = False

# 定义音乐类
class GameSound(object):
    def __init__(self):
        pygame.mixer.init() # 音乐模块初始化
        pygame.mixer.music.load("./images/Light It Up by Alexguz-完整版.mp3")
        pygame.mixer.music.set_volume(0.5) # 声音大小

        self.__bomb = pygame.mixer.Sound("./images/爆炸声06.mp3")

    def playBGM(self):
        pygame.mixer.music.play(-1) # 播放音乐 

    def playBombSound(self):
        pygame.mixer.Sound.play(self.__bomb)

# 创建管理类
class Manager(object):
    bg_size = (480,700)
    game_over_id = 11
    is_game_over = False
    creat_enemy_id = 10
    over_time = 3

    def __init__(self):
        # 创建窗口
        self.screen = pygame.display.set_mode((480,700), 0, 32)
        # 创建背景图片
        self.background = pygame.image.load("./images/background.png")
        # 初始化一个玩家精灵的group
        self.players = pygame.sprite.Group()
        # 初始化一个敌机精灵的gruop
        self.enemies = pygame.sprite.Group()
        # 初始化一个玩家爆炸的对象
        self.player_bomb = Bomb(self.screen, 'player')
        # 初始化一个敌机爆炸的对象
        self.enemy_bomb = Bomb(self.screen, 'enemy')
        # 初始化一个声音播放的对象
        self.sound = GameSound()



    def exit(self):
        print("退出")
        pygame.quit()
        exit()

    def game_over_timer(self):
        Manager.over_time -= 1
        if Manager.over_time == 0:
            pygame.time.set_timer(Manager.game_over_id, 0)
            Manager.over_time = 3
            Manager.is_game_over = False
            self.start_game()

    def start_game(self):
        # 重开游戏
        EnemyPlane.clear_bullets()
        HeroPlane.clear_bullets()
        manager = Manager()
        manager.main()

    def new_player(self):
        # 创建飞机对象，添加到玩家组
        player = HeroPlane(self.screen)
        self.players.add(player)

    def new_enemy(self):
        # 创建敌机对象，添加到敌机组
        enemy = EnemyPlane(self.screen)
        self.enemies.add(enemy)

    # def drawText(self, text, x, y, textHeight = 30, fontColor = (255,0,0), backgroundColor = None):
        # 通过文字获取字体对象

    def main(self):
        self.sound.playBGM()
        # 创建一个玩家
        self.new_player()
        # 开启创建敌机计时器
        pygame.time.set_timer(Manager.creat_enemy_id, 1000)
        while True:
            # 粘贴背景图片
            self.screen.blit(self.background, (0, 0))
            # 遍历事件
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                   self.exit()
                elif event.type == Manager.creat_enemy_id:
                    self.new_enemy()
                elif event.type == Manager.game_over_id:
                    self.game_over_timer()

            # 调用爆炸的对象
            self.player_bomb.draw()
            self.enemy_bomb.draw()

            if self.players.sprites():
                isover = pygame.sprite.spritecollide(self.players.sprites()[0], EnemyPlane.enemy_bullets, True)
                if isover:
                    Manager.is_game_over = True # 标志游戏结束
                    pygame.time.set_timer(Manager.game_over_id, 1000)
                    print("中弹")
                    self.player_bomb.action(self.players.sprites()[0].rect)
                    self.players.remove(self.players.sprites()[0])
                    self.sound.playBombSound()

            # 判断碰撞,如果碰撞则将两者消除，并返回一个字典
            iscrash = pygame.sprite.groupcollide(self.players, self.enemies, True, True)

            if iscrash:
                Manager.is_game_over = True
                pygame.time.set_timer(Manager.game_over_id, 1000)
                itmes = list(iscrash.items())[0]
                print(itmes)
                x = itmes[0]
                y = itmes[1][0]
                # 玩家爆炸图片
                self.player_bomb.action(x.rect)
                # 敌机爆炸图片
                self.enemy_bomb.action(y.rect)
                self.sound.playBombSound()

            is_enemy = pygame.sprite.groupcollide(HeroPlane.bullets, self.enemies, True, True)
            if is_enemy:
                items = list(is_enemy.items())[0]
                y = items[1][0]
                #敌机爆炸图片
                self.enemy_bomb.action(y.rect)
                #爆炸音效
                self.sound.playBombSound()

            is_player = pygame.sprite.groupcollide(EnemyPlane.enemy_bullets, self.players, True, True)
            if is_player:
                items = list(is_player.items())[0]
                x = items[0]
                # 玩家飞机爆炸图片
                self.player_bomb.action(x.rect)
                # 爆炸音效
                self.sound.playBombSound()


            # 显示玩家飞机和子弹
            self.players.update()
            # 显示敌方飞机和子弹
            self.enemies.update()

            pygame.display.update()
            time.sleep(0.01)

if __name__ == '__main__':
    manager = Manager()
    manager.main()

